/*
 *  Writer.h
 *  Compiler
 *
 *  Created by Jacopo De Stefani on 3/4/12.
 *  Copyright 2012 Politecnico di Milano. All rights reserved.
 *
 */

#ifndef SYMBOLTABLEENTRY_H
#define SYMBOLTABLEENTRY_H

#include <iostream>
#include <string>
#include <list>
#include <map>
#include <fstream>
#include <cstdlib>

using namespace std;

//User types definition
//typedef enum Types { INTEGER, BOOLEAN } TypesP;

class Writer
{
public: 
	
	//Static method to access the singleton implementation
	static Writer* getInstance();
	
	//PUSH OPERATIONS
	//Writes code corresponding to the move of a int value from sourceAddr on top of the stack.
	void movIntTop(int sourceAddr);
	//Writes code corresponding to the move of a bool value from sourceAddr on top of the stack.
	void movBoolTop(int sourceAddr);
	//Writes code corresponding to the push of a constant int value on top of the stack.
	void putIntTop(int intValue);
	//Writes code corresponding to the push of a constant bool value on top of the stack.
	void putBoolTop(bool boolValue);
	//Writes code corresponding to the duplication of the int value on top of the stack.
	void dupIntTop();
	//Writes code corresponding to the duplication of the bool value on top of the stack.
	void dupBoolTop();
	
	//POP OPERATIONS
	//Writes code corresponding to the store of the int value on top of the stack at destAddr location.
	void storeIntAt(int destAddr);
	//Writes code corresponding to the store of the bool value on top of the stack at destAddr location.
	void storeBoolAt(int destAddr);
	//Writes code corresponding to the pop of the value on top of the stack.
	void popTop();
	
	//ARITHMETIC OPERATIONS
	//Writes code corresponding to the add of the integer values occuping the two topmost locations on the stack.
	void addTop2();
	//Writes code corresponding to the subtraction of the integer values occuping the two topmost locations on the stack.
	void subTop2();
	//Writes code corresponding to the multiplication of the integer values occuping the two topmost locations on the stack.
	void mulTop2();
	//Writes code corresponding to the division of the integer values occuping the two topmost locations on the stack.
	void divTop2();
	//Writes code corresponding to the negation of the value on top of the stack.
	void negTop();
	
	//BOOLEAN OPERATIONS
	//Writes code corresponding to the logical and of the bool values occuping the two topmost locations on the stack.
	void andTop2();
	//Writes code corresponding to the logical or of the bool values occuping the two topmost locations on the stack.
	void orTop2();
	//Writes code corresponding to the logical not of the value on top of the stack.
	void notTop();
	
	//COMPARISON OPERATIONS
	//Writes code corresponding to the "greater or equal than" comparison of the int values occuping the two topmost locations on the stack.
	void geqTop2();
	//Writes code corresponding to the "less or equal than" comparison of the int values occuping the two topmost locations on the stack.
	void leqTop2();
	//Writes code corresponding to the "greater than" comparison of the int values occuping the two topmost locations on the stack.
	void grtTop2();
	//Writes code corresponding to the "less than" comparison of the int values occuping the two topmost locations on the stack.
	void lesTop2();
	//Writes code corresponding to the "equal to" comparison of the int values occuping the two topmost locations on the stack.
	void equTop2();
	//Writes code corresponding to the "not equal to" comparison of the int values occuping the two topmost locations on the stack.
	void neqTop2();
	
	//I/O OPERATIONS
	//Writes code corresponding to the write I/O operation of the value on top of the stack.
	void printTop();
	//Writes code corresponding to the read I/O operation whose result is put on top of the stack.
	void readToTop();
	
	//JUMP OPERATIONS
	//Writes code corresponding to the definition of a label to allow jumps.
	void defLabel(string label);
	//Writes code corresponding to the unconditional jump to label.
	void uncondJumpTo(string label);
	//Writes code corresponding to the conditional jump to label only if the value on top of the stack is false.
	void condFalseJumpTo(string label);
	
	//SUBROUTINE OPERATIONS
	//Writes code corresponding to the allocation of a new stack frame, given the current nesting (0 : Main function, 1 : Subroutine).
	void allocSF(int currNest);
	//Writes code corresponding to the function call of funcName with parNum parameters.
	void callFunc(int parNum,string funcName);
	//Writes code corresponding to the return instruction of a function.
	void retFunc();
	//Writes code corresponding to the return instruction of a procedure.
	void retProc();
	
	//SUBROUTINE PUSH OPERATIONS
	//Writes code corresponding to the move of a int value from sourceAddr on top of the current stack frame.
	void movIntTopFunc(int sourceAddr);
	//Writes code corresponding to the move of a bool value from sourceAddr on top of the current stack frame.
	void movBoolTopFunc(int sourceAddr);
	//Writes code corresponding to the move of a int value from sourceAddr on top of the global stack frame.
	void movIntTopGlob(int sourceAddr);
	//Writes code corresponding to the move of a bool value from sourceAddr on top of the global stack frame.
	void movBoolTopGlob(int sourceAddr);
	
	//SUBROUTINE POP OPERATIONS
	//Writes code corresponding to the store of the int value on top of the stack at destAddr relative address with respect to current stack frame.
	void storeIntFunc(int destAddr);
	//Writes code corresponding to the store of the bool value on top of the stack at destAddr relative address with respect to current stack frame.
	void storeBoolFunc(int destAddr);
	//Writes code corresponding to the store of the int value on top of the stack at destAddr absolute address. 
	void storeIntGlob(int destAddr);
	//Writes code corresponding to the store of the bool value on top of the stack at destAddr absolute address.
	void storeBoolGlob(int destAddr);
	//Writes code corresponding to the end of the program.
	void endProg();
	
	//Get and Set Methods to access attributes
	int		getIfCtr(){return ifctr;}
	int		getLoopCtr(){return loopctr;}
	
	void	setIfCtr(int value){ifctr = value;}
	void	setLoopCtr(int value){loopctr = value;}
	
private:
	//Constructor
	Writer(): ifctr(0),loopctr(0){};
	//Initialization method
	void initWriter();
	//Output file
	fstream gpCodeFile;
	
	//Counter to distinguish if branches.
	int ifctr;
	//Counter to distinguish loops.
	int loopctr;
        //Singleton implementation of the class
	static Writer* uniqueInstance;
	
	
};
#endif
